home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-06-30 | 19.2 KB | 631 lines |
- /*
- * @(#)AbstractOptionPaneUI.java 1.19 98/02/05
- *
- * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
-
- package com.sun.java.swing.plaf.basic;
-
- import com.sun.java.swing.*;
- import com.sun.java.swing.plaf.*;
- import com.sun.java.swing.event.*;
- import java.awt.*;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.io.Serializable;
-
- /**
- * AbstractMessagePaneUI provides a means to place an icon, message and
- * buttons into a Container. The layout will look like:<p>
- * <pre>
- * ------------------
- * | i | message |
- * | c | message |
- * | o | message |
- * | n | message |
- * ------------------
- * | buttons |
- * |________________|
- * </pre>
- * icon is an instance of Icon that is wraped inside a JLabel.
- * The message is an opaque object and is tested for the following:
- * if the message is a Component it is added to the Container, if
- * it is an Icon it is wrapped inside a JLabel and added to the
- * Container otherwise it is wrapped inside a JLabel.
- * <p>
- * The Container, message, icon, and buttons are all determined from
- * abstract methods.
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- *
- * @version 1.19 02/05/98
- * @author James Gosling
- * @author Scott Violet
- */
- abstract public class AbstractOptionPaneUI extends OptionPaneUI implements Serializable
- {
- /** Component to receive focus when messaged with selectInitialValue. */
- protected Component initialFocusComponent;
-
- /** This is set to true in validateComponent if a Component is contained
- * in either the message or the buttons. */
- protected boolean hasCustomComponents;
-
- /**
- * Icon to display, null implies no Icon.
- */
- abstract public Icon getIcon();
-
- /**
- * Returns the message to display.
- */
- abstract public Object getMessage();
-
- /**
- * Returns the buttons to display.
- */
- abstract public Object[] getButtons();
-
- /**
- * Returns the Container to place all the Components in.
- */
- abstract public Container getContainer();
-
- /**
- * Returns the initial index into buttons to select.
- */
- abstract public int getInitialIndex();
-
- protected Color getLabelColor() { return UIManager.getColor( "OptionPane.foreground" ); }
-
- /**
- * Returns false. This is queried to determine if the buttons should
- * be sized to the same width.
- */
- public boolean getSizeButtonsToSameWidth() {
- return false;
- }
-
- /**
- * Returns true if in the last call to validateComponent the message
- * or buttons contained a subclass of Component.
- */
- public boolean containsCustomComponents() {
- return hasCustomComponents;
- }
-
- /**
- * Returns the maximum number of characters to place on a line.
- * Default is to return Integer.MAX_VALUE. Concrete implementations
- * may want to return a value that means something.
- */
- public int getMaxCharactersPerLineCount() {
- return Integer.MAX_VALUE;
- }
-
- /**
- * Requests focus on the initial value.
- */
- public void selectInitialValue() {
- if (initialFocusComponent != null)
- initialFocusComponent.requestFocus();
-
- if (initialFocusComponent instanceof JButton) {
- JRootPane root = SwingUtilities.getRootPane(initialFocusComponent);
- if (root != null) {
- root.setDefaultButton((JButton)initialFocusComponent);
- }
- }
- }
-
- /**
- * Recursively creates new JLabel instances to represent <code>d</code>.
- * Each JLabel instance is added to <code>c</code>.
- */
- protected void burstStringInto(Container c, String d, int maxll) {
- // Primitive line wrapping
- int len = d.length();
- if (len <= 0)
- return;
- if (len > maxll) {
- int p = d.lastIndexOf(' ', maxll);
- if (p <= 0)
- p = d.indexOf(' ', maxll);
- if (p > 0 && p < len) {
- burstStringInto(c, d.substring(0, p), maxll);
- burstStringInto(c, d.substring(p + 1), maxll);
- return;
- }
- }
- c.add(new JLabel(d, JLabel.LEFT));
- }
-
- /**
- * Creates the appropriate object to represent <code>d</code> and
- * places it into <code>container</code>. If <code>d</code> is an
- * instance of Component, it is added directly, if it is an Icon,
- * a JLabel is created to represent it, otherwise a JLabel is
- * created for the string, if <code>d</code> is an Object[], this
- * method will be recursively invoked for the children.
- * <code>internallyCreated</code> is true if Objc is an instance
- * of Component and was created internally by this method (this is
- * used to correctly set hasCustomComponents only if !internallyCreated).
- */
- protected void appendDescription(Container container,
- GridBagConstraints cons,
- Object d, int maxll,
- boolean internallyCreated) {
- if (d == null)
- return;
- if (d instanceof Component) {
- cons.fill = GridBagConstraints.HORIZONTAL;
- cons.weightx = 1;
- container.add((Component) d, cons);
- cons.weightx = 0;
- cons.fill = GridBagConstraints.NONE;
- cons.gridy++;
- if(!internallyCreated)
- hasCustomComponents = true;
- } else if (d instanceof Object[]) {
- Object [] da = (Object[]) d;
- for (int i = 0; i < da.length; i++)
- appendDescription(container, cons, da[i], maxll, false);
- } else if (d instanceof Icon) {
- JLabel label = new JLabel( (Icon)d, maxll );
- label.setForeground( getLabelColor() );
- appendDescription(container, cons, label, maxll, true);
- } else {
- String s = d.toString();
- int len = s.length();
- if (len <= 0)
- return;
- int nl = s.indexOf('\n');
- if (nl >= 0) {
- // break up newlines
- if(nl == 0)
- appendDescription(container, cons, new Component() {
- public Dimension getPreferredSize() {
- Font f = getFont();
-
- if(f != null)
- return new Dimension(1, f.getSize() + 2);
- return new Dimension(0, 0);
- }
- }, maxll, true);
- else
- appendDescription(container, cons, s.substring(0, nl),
- maxll, false);
- appendDescription(container, cons, s.substring(nl + 1), maxll,
- false);
- } else if (len > maxll) {
- Container c = Box.createVerticalBox();
- burstStringInto(c, s, maxll);
- appendDescription(container, cons, c, maxll, true );
- } else {
- JLabel label = new JLabel( s, JLabel.LEFT );
- label.setForeground( getLabelColor() );
- appendDescription(container, cons, label, maxll, true);
- }
- }
- }
-
-
- /**
- * Creates the appropriate object to represent each of the objects in
- * <code>buttons</code> and adds it to <code>container</code>. This
- * differs from appendDescription in that it will recurse on
- * <code>buttons</code> and that if button is not a Component
- * it will create an instance of JButton, that when pressed will
- * invoke <code>createdButtonFired</code> with the appropriate
- * index.
- */
- protected void appendButtons(Container container, Object[] buttons,
- int initialIndex) {
- if(buttons != null && buttons.length > 0) {
- boolean sizeButtonsToSame = getSizeButtonsToSameWidth();
- boolean createdAll = true;
- int numButtons = buttons.length;
- JButton[] createdButtons = null;
- int maxWidth = 0;
-
- if(sizeButtonsToSame)
- createdButtons = new JButton[numButtons];
-
- for(int counter = 0; counter < numButtons; counter++) {
- Object anO = buttons[counter];
- Component newComponent;
-
- if(anO instanceof Component) {
- createdAll = false;
- newComponent = (Component)anO;
- container.add(newComponent);
- hasCustomComponents = true;
- }
- else {
- JButton aButton;
-
- if(anO instanceof Icon)
- aButton = new JButton((Icon)anO);
- else
- aButton = new JButton(anO.toString());
- container.add(aButton);
-
- final int buttonIndex = counter;
-
- aButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- createdButtonFired(buttonIndex);
- }
- });
- newComponent = aButton;
- }
- if(sizeButtonsToSame && createdAll &&
- (newComponent instanceof JButton)) {
- createdButtons[counter] = (JButton)newComponent;
- maxWidth = Math.max(maxWidth,
- newComponent.getMinimumSize().width);
- }
- if(counter == initialIndex) {
- initialFocusComponent = newComponent;
- if (initialFocusComponent instanceof JButton) {
- JButton defaultB = (JButton)initialFocusComponent;
- defaultB.addAncestorListener(new AncestorListener() {
- public void ancestorAdded(AncestorEvent e) {
- JButton defaultButton = (JButton)e.getComponent();
- JRootPane root = SwingUtilities.getRootPane(defaultButton);
- if (root != null) {
- root.setDefaultButton(defaultButton);
- }
- }
- public void ancestorRemoved(AncestorEvent event) {}
- public void ancestorMoved(AncestorEvent event) {}
- });
- }
- }
- }
- ((SyncingLayoutManager)container.getLayout()).
- setSyncsAll((sizeButtonsToSame && createdAll));
- /* Set the padding, windows seems to use 8 if <= 2 components,
- otherwise 4 is used. It may actually just be the size of the
- buttons is always the same, not sure. */
- if(sizeButtonsToSame && createdAll) {
- JButton aButton;
- int padSize;
-
- if(numButtons <= 2)
- padSize = 8;
- else
- padSize = 4;
- for(int counter = 0; counter < numButtons; counter++) {
- aButton = createdButtons[counter];
- aButton.setMargin(new Insets(2, padSize, 2, padSize));
- }
- }
- }
- }
-
- /**
- * Invoked when a button that was created in <code>appendButtons</code>
- * has been pressed. <code>buttonIndex</code> identifies the index
- * of the button from the <code>buttons</code>array that was passed
- * into <code>appendButtons</code>.
- */
- public void createdButtonFired(int buttonIndex) {
- }
-
- /**
- * Messaged from <code>validateComponent</code> to remove all the
- * components from <code>container</code>. This invokes removeAll
- * on <code>container</code>, but is provided should subclasses wish
- * to not remove everything.
- */
- protected void emptyContainer(Container container) {
- container.removeAll();
- }
-
- /**
- * Creates and adds a JLabel representing the icon returned from
- * <code>getIcon</code> to <code>top</code>. This is messaged from
- * <code>createBody</code>
- */
- protected void addIcon(Container top) {
- /* Create the icon. */
- Icon sideIcon = getIcon();
-
- if (sideIcon != null) {
- JLabel iconLabel = new JLabel(sideIcon);
-
- iconLabel.setVerticalAlignment(SwingConstants.TOP);
- top.add(iconLabel, BorderLayout.WEST);
- }
- }
-
- /**
- * Messaged from validateComponent to create a Container containing the
- * body of the message. The icon is the created by calling
- * <code>addIcon</code>.
- */
- protected Container createBody() {
- Container top = new Container() {
- public Insets getInsets() {
- return getBodyInsets();
- }
- };
-
- top.setLayout(new BorderLayout());
-
- /* Fill the body. */
- GridBagConstraints cons = new GridBagConstraints();
- Container body = new Container() {};
- Container realBody = new Container() {};
-
- realBody.setLayout(new BorderLayout());
- realBody.add(new Container() {
- public Dimension getPreferredSize() {
- return new Dimension(15, 1);
- }
- }, BorderLayout.WEST);
- realBody.add(body, BorderLayout.CENTER);
-
- body.setLayout(new GridBagLayout());
- cons.gridx = cons.gridy = 0;
- cons.gridwidth = GridBagConstraints.REMAINDER;
- cons.gridheight = 1;
- cons.anchor = GridBagConstraints.WEST;
- cons.insets = new Insets(0,0,3,0);
-
- appendDescription(body, cons, getMessage(),
- getMaxCharactersPerLineCount(), false);
- top.add(realBody, BorderLayout.CENTER);
-
- addIcon(top);
- return top;
- }
-
- /**
- * Returns the insets to be used in the Container housing the buttons.
- */
- protected Insets getButtonInsets() {
- return new Insets(6, 0, 0, 0);
- }
-
- /**
- * Returns the insets to be used for the body, the body contains both
- * the image and the actual message.
- */
- protected Insets getBodyInsets() {
- return new Insets(0, 0, 0, 0);
- }
-
- /**
- * Creates and returns a Container containin the buttons. The buttons
- * are created by calling <code>getButtons</code>.
- */
- protected Container createButtons() {
- /* And the bottom for all the buttons. */
- Container bottom = new Container() {
- public Insets getInsets() {
- return getButtonInsets();
- }
- };
-
- bottom.setLayout(new SyncingLayoutManager(true, 6));
- appendButtons(bottom, getButtons(), getInitialIndex());
- return bottom;
- }
-
- /**
- * Removes all the components from the Container, adds the icon,
- * message and buttons.
- */
- protected void validateComponent() {
- Container container = getContainer();
-
- hasCustomComponents = false;
- initialFocusComponent = null;
- if(container != null) {
- emptyContainer(container);
- container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
- container.add(createBody());
- container.add(createButtons());
- }
- }
-
-
- /**
- * SyncingLayoutManager acts similiar to FlowLayout. It lays out all
- * components from left to right. If syncsAll is true, the widths
- * of each component will be set to the largest preferred size width.
- */
- public static class SyncingLayoutManager implements LayoutManager,
- Serializable {
- protected boolean syncsAll;
- protected int padding;
- /** If true, children are lumped together in parent. */
- protected boolean centersChildren;
-
- public SyncingLayoutManager(boolean syncsAll, int padding) {
- this.syncsAll = syncsAll;
- this.padding = padding;
- centersChildren = true;
- }
-
- public void setSyncsAll(boolean newValue) {
- syncsAll = newValue;
- }
-
- public boolean getSyncsAll() {
- return syncsAll;
- }
-
- public void setPadding(int newPadding) {
- this.padding = newPadding;
- }
-
- public int getPadding() {
- return padding;
- }
-
- public void setCentersChildren(boolean newValue) {
- centersChildren = newValue;
- }
-
- public boolean getCentersChildren() {
- return centersChildren;
- }
-
- public void addLayoutComponent(String string, Component comp) {
- }
-
- public void layoutContainer(Container container) {
- Component[] children = container.getComponents();
-
- if(children != null && children.length > 0) {
- int numChildren = children.length;
- Dimension[] sizes = new Dimension[numChildren];
- int counter;
- int yLocation = container.getInsets().top;
-
- if(syncsAll) {
- int maxWidth = 0;
-
- for(counter = 0; counter < numChildren; counter++) {
- sizes[counter] = children[counter].getPreferredSize();
- maxWidth = Math.max(maxWidth, sizes[counter].width);
- }
-
- int xLocation;
- int xOffset;
-
- if(getCentersChildren()) {
- xLocation = (container.getSize().width -
- (maxWidth * numChildren +
- (numChildren - 1) * padding)) / 2;
- xOffset = padding + maxWidth;
- }
- else {
- if(numChildren > 1) {
- xLocation = 0;
- xOffset = (container.getSize().width -
- (maxWidth * numChildren)) /
- (numChildren - 1) + maxWidth;
- }
- else {
- xLocation = (container.getSize().width -
- maxWidth) / 2;
- xOffset = 0;
- }
- }
- for(counter = 0; counter < numChildren; counter++) {
- children[counter].setBounds(xLocation, yLocation,
- maxWidth,
- sizes[counter].height);
- xLocation += xOffset;
- }
- }
- else {
- int totalWidth = 0;
-
- for(counter = 0; counter < numChildren; counter++) {
- sizes[counter] = children[counter].getPreferredSize();
- totalWidth += sizes[counter].width;
- }
- totalWidth += ((numChildren - 1) * padding);
-
- boolean cc = getCentersChildren();
- int xOffset;
- int xLocation;
-
- if(cc) {
- xLocation = (container.getSize().width -
- totalWidth) / 2;
- xOffset = padding;
- }
- else {
- if(numChildren > 1) {
- xOffset = (container.getSize().width -
- totalWidth) / (numChildren - 1);
- xLocation = 0;
- }
- else {
- xLocation = (container.getSize().width -
- totalWidth) / 2;
- xOffset = 0;
- }
- }
-
- for(counter = 0; counter < numChildren; counter++) {
- children[counter].setBounds(xLocation, yLocation,
- sizes[counter].width, sizes[counter].height);
- xLocation += xOffset + sizes[counter].width;
- }
- }
- }
- }
-
- public Dimension minimumLayoutSize(Container c) {
- if(c != null) {
- Component[] children = c.getComponents();
-
- if(children != null && children.length > 0) {
- Dimension aSize;
- int numChildren = children.length;
- int height = 0;
- Insets cInsets = c.getInsets();
- int extraHeight = cInsets.top + cInsets.bottom;
-
- if(syncsAll) {
- int maxWidth = 0;
-
- for(int counter = 0; counter < numChildren; counter++){
- aSize = children[counter].getPreferredSize();
- height = Math.max(height, aSize.height);
- maxWidth = Math.max(maxWidth, aSize.width);
- }
- return new Dimension(maxWidth * numChildren +
- (numChildren - 1) * padding,
- extraHeight + height);
- }
- else {
- int totalWidth = 0;
-
- for(int counter = 0; counter < numChildren; counter++){
- aSize = children[counter].getPreferredSize();
- height = Math.max(height, aSize.height);
- totalWidth += aSize.width;
- }
- totalWidth += ((numChildren - 1) * padding);
- return new Dimension(totalWidth, extraHeight + height);
- }
- }
- }
- return new Dimension(0, 0);
- }
-
- public Dimension preferredLayoutSize(Container c) {
- return minimumLayoutSize(c);
- }
-
- public void removeLayoutComponent(Component c) { }
- }
- }
-